import { compact, forEach, mapValues } from "lodash";
import xlsx, { WorkSheet } from 'xlsx';

export type TXLSXResult = { companyName: string; percent: number; data: { [key: string]: number } }

export function readXLSX(file: Blob): Promise<TXLSXResult> {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.onload = function () {
      const parser = xlsx.read(this.result, { type: "binary" })
      const data: { code: string; name: string; percent: number; }[] = xlsx.utils.sheet_to_json(parser.Sheets[parser.SheetNames[0]])
      const lastData = data.pop() as { code: string; name: string; percent: number; };
      resolve({
        companyName: lastData.code.trim(),
        percent: lastData.percent,
        data: Object.assign({}, ...data.map(e => ({
          [e.code.toUpperCase()]: e.percent
        })))
      })
    };
    reader.onerror = function () {
      reject("xls文件读取失败！")
      console.log('xls文件读取失败！');
    };
    reader.readAsBinaryString(file)
  });
}

export function getTxtStr(file: any, encode = "GB2312") {
  return new Promise<string>((resolve, reject) => {
    const reader = new FileReader();
    reader.onload = function (e) {
      resolve((e.target?.result as string) || "");
    }
    reader.onerror = function () {
      reject(`文件${file.name} 读取失败`);
    }
    reader.readAsText(file, encode);
  })
}

export function formatFileStr(str: string) {
  if (str) {
    if (!str.includes("成交记录") || !str.includes("持仓汇总")) {
      return null
    }
    const ret: {
      conpanyName: string;
      clientName: string;
      content: { [key: string]: number }
    } = {
      conpanyName: "",
      clientName: "",
      content: {}
    }
    const comapnyNames = str.match(/.*\n?/)
    if (comapnyNames?.length) {
      ret.conpanyName = comapnyNames[0].trim()
    }
    const clientNames = str.match(/客户名称 Client Name：.*\n?/)
    if (clientNames?.length) {
      ret.clientName = clientNames[0].replace("客户名称 Client Name：", "").trim()
    }
    const middleStr = str.replace(/\r/g, '').replace(/\n/g, "##enter##")
    const strSptList = middleStr.replace(/^.*成交记录(.*)持仓汇总.*$/, "$1").split("##enter##")
    let codeColIndex = 4;
    let percentColIndex = 11
    // 减号出现次数
    let minusTimes = 0
    const list = compact(strSptList.map((row, ri) => {
      if (minusTimes === 3) {
        return null
      } else if (minusTimes < 3 && row.includes("-----------------------")) {
        minusTimes++
      }
      const arr = row.split("|")
      if (ri < 10 && row.includes("成交日期")) {
        const trimed = arr.map(e => e.trim())
        codeColIndex = trimed.indexOf("合约")
        percentColIndex = trimed.indexOf("手续费")
      }
      if (arr.length > percentColIndex) {
        const name = arr[codeColIndex].trim().toUpperCase()
        const value = parseFloat(arr[percentColIndex].trim())
        if (isNaN(value) || !name) {
          return null
        }
        return { name, value }
      }
      return null
    }))
    list.forEach(ele => {
      if (ret.content[ele.name]) {
        ret.content[ele.name] += Math.round(ele.value * 100);
      } else {
        ret.content[ele.name] = Math.round(ele.value * 100);
      }
    })
    ret.content = mapValues(ret.content, e => e / 100)
    return ret
  }
}

export function calcResult(param: {
  conpanyName: string;
  clientName: string;
  content: {
    [key: string]: number;
  };
}, exchangePercent: TXLSXResult) {
  const exchgp = exchangePercent.data
  const coPercent = exchangePercent.percent
  const data: {
    code: string;
    fee: number;
    exchangePercent: string;
    exchange: number;
    coPercent: string;
    actualsum: number;
  }[] = []
  forEach(param.content, function (value, key) {
    const keyCode = key.replace(/(^[A-Z]{0,5}).*$/, "$1")
    const chgP = typeof exchgp[key] === "number" ? exchgp[key] : exchgp[keyCode]
    const exchange = parseFloat((chgP * value).toFixed(2))
    data.push({
      code: key,
      fee: value,
      exchangePercent: chgP * 100 + "%",
      exchange: exchange,
      coPercent: coPercent * 100 + "%",
      actualsum: parseFloat((coPercent * exchange).toFixed(2))
    })
  });
  return data
}
export class ExportExcel {
  worksheets: WorkSheet[] = []
  add(data: { [key: string]: string | number }[], columnName: string[]) {
    const worksheet = xlsx.utils.json_to_sheet<{ [key: string]: string | number }>(data)
    this.worksheets.push(worksheet);
    xlsx.utils.sheet_add_aoa(worksheet, [columnName], { origin: "A1" });
  }
  __changeData(sss: string) {
    //如果存在ArrayBuffer对象(es6) 最好采用该对象
    if (typeof ArrayBuffer !== "undefined") {
      //1、创建一个字节长度为sss.length的内存区域
      const buf = new ArrayBuffer(sss.length);
      //2、创建一个指向buf的Unit8视图，开始于字节0，直到缓冲区的末尾
      const view = new Uint8Array(buf);
      //3、返回指定位置的字符的Unicode编码
      for (let i = 0; i !== sss.length; ++i) {
        view[i] = sss.charCodeAt(i) & 0xff;
      }
      return buf;
    } else {
      const buf2: number[] = new Array(sss.length);
      for (let k = 0; k !== sss.length; ++k) {
        buf2[k] = sss.charCodeAt(k) & 0xff;
      }
      return buf2;
    }
  }
  save(fileName: string, SheetNames: string[]) {
    const Sheets: { [sheet: string]: WorkSheet } = {}
    this.worksheets.forEach((sheet, index) => {
      Sheets[SheetNames[index]] = sheet
    })
    const rrr = xlsx.write(
      {
        SheetNames,
        Sheets,
        Props: {}
      },
      {
        bookType: "xlsx",
        bookSST: false,
        type: "binary"
      }
    )
    const obj = new Blob(
      [
        this.__changeData(rrr) as ArrayBuffer
      ],
      { type: "application/octet-stream" }
    );
    const tmpA = document.createElement("a");
    tmpA.download = fileName ? fileName + ".xlsx" : new Date().getTime() + ".xlsx";
    tmpA.href = URL.createObjectURL(obj); //绑定a标签
    tmpA.click(); //模拟点击实现下载
    setTimeout(function () {
      //延时释放
      URL.revokeObjectURL(tmpA.href); //用URL.revokeObjectURL()来释放这个object URL
    }, 100);
  }
}